using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
using System.IO;
using System.Xml.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Reflection;
using SypConst.Garbage;
using SypConst.Path;
using SypEngine;


namespace SypEngine
{   
    public class SypCommandDispatcher : SypGarbageObject
    {
        /// <summary>
        /// 
        /// </summary>
        /// 
        private Hashtable SypCmdHandlerList = null;

        #region controllers Methods
        private SypSiteHandler SypSites = null;

        public SypSite GetSite(int SiteId)
        {
            lock (SypSites)
            {
                SypSite site = SypSites.GetSiteConfig(SiteId);
                if (site != null)
                {
                    SypSite MyCloneObject = (SypSite)site.Clone();
                    return MyCloneObject;
                }
                else
                    return null;
            }
        }

        public List<SypSite> GetAllSites()
        {
            lock (SypSites)
            {
                List<SypSite> myListSite = new List<SypSite>();
                foreach (SypSite mysite in SypSites.Sites)
                {
                    myListSite.Add((SypSite)mysite.Clone());
                }
                return myListSite;
            }
        }

       


        
        #endregion


        public void Dispatch(String CommandLine)
        {
            String[] parameters = Regex.Split(CommandLine, SypGarbage.COMMAND_SEPARATOR.ToString() + "+(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))");

            if (parameters.Length > 1)
            {
                parameters[parameters.Length - 2] = parameters[parameters.Length - 2].Replace("\r\n", "");
                parameters[parameters.Length - 2] = parameters[parameters.Length - 2].Replace("\n", "");
                parameters[parameters.Length - 2] = parameters[parameters.Length - 2].Replace("\"", "");
            }

            //dispatching
            if (parameters[0].ToLower().Contains("online"))
                ((SypCommandHandler)SypCmdHandlerList["Online"]).Enqueue(parameters);
            else
                ((SypCommandHandler)SypCmdHandlerList["Local"]).Enqueue(parameters);

        }


        private void AddListenner(string ListenerName, VisitorCallBack[] Callbacks)
        {
            if (SypCmdHandlerList  == null)
                SypCmdHandlerList = new Hashtable();

            Assembly currentAssembly = Assembly.LoadFrom(SypGarbage.ASSEMBLY_NAME);

            foreach (Type cls in currentAssembly.GetTypes())
            {
                if (cls.Name.Equals("Syp"+ListenerName+"CommandHandler")) 
                {
                    ConstructorInfo ctor = cls.GetConstructor(new Type[] { typeof(SetText), typeof(VisitorCallBack[]), typeof(SypSiteHandler) });
                    if (ctor != null)
                    {
                        object Instance = ctor.Invoke(new object[] { OutputMethod, Callbacks, SypSites });
                        SypCmdHandlerList.Add(ListenerName, Instance);
                    }

                }
            }
        }


        public SypCommandDispatcher(SetText WriteMethod, VisitorCallBack[] Callbacks)
            : base(WriteMethod)
        {
            SypPathHandler.CreateLocalFolders();

            if (SypSites == null)
            {
                SypSites = new SypSiteHandler(WriteMethod, Callbacks);
                SypSites.CheckAvailableSites();
            }

            AddListenner("Online", Callbacks);
            AddListenner("Local", Callbacks);
        }

        public void Start()
        {
            foreach (SypCommandHandler SypCmdHander in SypCmdHandlerList.Values)
            {
                SypCmdHander.Start();
            }
        }

        public void Terminate()
        {
            foreach (SypCommandHandler SypCmdHander in SypCmdHandlerList.Values)
            {
                SypCmdHander.Terminate();
            }
        }


    }
}
